#include "stdafx.h"
#include "ParseCode.h"

/*************************************************************
* ItemResult
*************************************************************/
ItemResult::ItemResult()
{
	this->_code = "";
	this->_left = 0;
	this->_top = 0;
	this->_width = 0;
	this->_height = 0;
}
ItemResult::ItemResult(string code,int left,int top,int width,int height)
{
	this->_code = code;
	this->_left = left;
	this->_top = top;
	this->_width = width;
	this->_height = height;
}
string ItemResult::Code() const
{
	return this->_code;
}
int ItemResult::Left() const
{
	return this->_left;
}
int ItemResult::Top() const
{
	return this->_top;
}
int ItemResult::Width() const
{
	return this->_width;
}
int ItemResult::Height() const
{
	return this->_height;
}
void ItemResult::SetCode(string code)
{
	this->_code = code;
}
void ItemResult::SetLeft(int left)
{
	this->_left = left;
}
void ItemResult::SetTop(int top)
{
	this->_top = top;
}
void ItemResult::SetWidth(int width)
{
	this->_width = width;
}
void ItemResult::SetHeight(int height)
{
	this->_height = height;
}

/*************************************************************
* StructParam
*************************************************************/
StructParam::StructParam(string structCode,int unitCount)
{
	this->_structCode = structCode;
	this->_unitCount = unitCount;
	this->_ranges = new Range[this->_unitCount];
	this->_rangeCount = 0;
}
string StructParam::Code() const
{
	return this->_structCode;
}
int StructParam::UnitCount() const
{
	return this->_unitCount;
}
void StructParam::AddRange(Range range)
{
	if(this->_rangeCount >= this->UnitCount()) return;
	this->_ranges[this->_rangeCount] = range;
	this->_rangeCount ++ ;
}
Range StructParam::GetRange(int index) const
{
	return this->_ranges[index];
}

/*************************************************************
* StructParams
*************************************************************/
StructParams* StructParams::p_sp = 0;
StructParams::StructParams()
{
	this->initialMap();
}
StructParams::~StructParams()
{
	for(map<string,StructParam*>::iterator it = this->_structParams.begin();it != this->_structParams.end();it++)
	{
		delete it->second;
	}
	this->_structParams.clear();
	StructParams::p_sp = 0;
}
StructParams* StructParams::Create()
{
	if(StructParams::p_sp == 0)
		StructParams::p_sp = new StructParams();
	return StructParams::p_sp;
}
void StructParams::initialMap()
{
	StructParam* H = new StructParam("H",2);
	H->AddRange(Range(0.0,0.8,0.0,1.0));
	H->AddRange(Range(0.2,1.0,0.0,1.0));
	this->_structParams["H"] = H;

	StructParam* J = new StructParam("J",2);
	J->AddRange(Range(0.0,1.0,0.0,0.8));
	J->AddRange(Range(0.0,1.0,0.2,1.0));
	this->_structParams["J"] = J;

	StructParam* L = new StructParam("L",2);
	L->AddRange(Range(0.0,1.0,0.0,1));
	L->AddRange(Range(0.1,0.9,0.1,0.9));
	this->_structParams["L"] = L;

	StructParam* G = new StructParam("G",1);
	G->AddRange(Range(0.0,1.0,0.0,1));
	this->_structParams["G"] = G;

	StructParam* K = new StructParam("K",3);
	K->AddRange(Range(0.0,1.0,0.0,0.6));
	K->AddRange(Range(0.0,1.0,0.2,0.8));
	K->AddRange(Range(0.0,1.0,0.4,1.0));
	this->_structParams["K"] = K;

	StructParam* U = new StructParam("U",4);
	U->AddRange(Range(0.0,1.0,0.0,0.4));
	U->AddRange(Range(0.0,1.0,0.2,0.6));
	U->AddRange(Range(0.0,1.0,0.4,0.8));
	U->AddRange(Range(0.0,1.0,0.6,1.0));
	this->_structParams["U"] = U;

	StructParam* V = new StructParam("V",5);
	V->AddRange(Range(0.0,1.0,0.0,0.5));
	V->AddRange(Range(0.0,1.0,0.2,0.6));
	V->AddRange(Range(0.0,1.0,0.4,0.8));
	V->AddRange(Range(0.0,1.0,0.5,0.9));
	V->AddRange(Range(0.0,1.0,0.6,1.0));
	this->_structParams["V"] = V;

	StructParam* I = new StructParam("I",3);
	I->AddRange(Range(0.0,0.6,0.0,1.0));
	I->AddRange(Range(0.2,0.8,0.0,1.0));
	I->AddRange(Range(0.4,1.0,0.0,1.0));
	this->_structParams["I"] = I;

	StructParam* X = new StructParam("X",4);
	X->AddRange(Range(0.0,0.4,0.0,1.0));
	X->AddRange(Range(0.2,0.6,0.0,1.0));
	X->AddRange(Range(0.4,0.8,0.0,1.0));
	X->AddRange(Range(0.6,1.0,0.0,1.0));
	this->_structParams["X"] = X;

	StructParam* M = new StructParam("M",2);
	M->AddRange(Range(0.0,1.0,0.0,1));
	M->AddRange(Range(0.1,0.9,0.1,1.0));
	this->_structParams["M"] = M;

	StructParam* O = new StructParam("O",2);
	O->AddRange(Range(0.0,1.0,0.0,1));
	O->AddRange(Range(0.1,1,0.1,1.0));
	this->_structParams["O"] = O;

	StructParam* P = new StructParam("P",2);
	P->AddRange(Range(0.0,1.0,0.0,1));
	P->AddRange(Range(0.1,1,0,0.9));
	this->_structParams["P"] = P;

	StructParam* Q = new StructParam("Q",2);
	Q->AddRange(Range(0.0,1.0,0.0,1));
	Q->AddRange(Range(0.1,1,0.1,0.9));
	this->_structParams["Q"] = Q;

	StructParam* R = new StructParam("R",2);
	R->AddRange(Range(0.0,1,0.0,1));
	R->AddRange(Range(0,0.9,0.1,1));
	this->_structParams["R"] = R;

	StructParam* N = new StructParam("N",2);
	N->AddRange(Range(0.0,1.0,0.0,1));
	N->AddRange(Range(0.1,0.9,0.0,0.9));
	this->_structParams["N"] = N;

	StructParam* S = new StructParam("S",3);
	S->AddRange(Range(0.0,1.0,0.0,0.6));
	S->AddRange(Range(0.0,0.6,0.4,1));
	S->AddRange(Range(0.4,1,0.4,1));
	this->_structParams["S"] = S;

	StructParam* T = new StructParam("T",4);
	T->AddRange(Range(0.0,0.6,0.0,0.6));
	T->AddRange(Range(0.4,1,0.0,0.6));
	T->AddRange(Range(0.0,0.6,0.4,1));
	T->AddRange(Range(0.4,1,0.4,1));
	this->_structParams["T"] = T;

	StructParam* W = new StructParam("W",4);
	W->AddRange(Range(0.0,0.6,0.0,0.6));
	W->AddRange(Range(0.4,1,0.0,0.6));
	W->AddRange(Range(0.0,0.6,0.4,1));
	W->AddRange(Range(0.4,1,0.4,1));
	this->_structParams["W"] = W;
}
StructParam* StructParams::Get(string structCode)
{	
	return this->_structParams[structCode];
}


/************************************************************************
* Range
*************************************************************************/
Range::Range()
{
	this->_x_start = 0.0;
	this->_x_end = 1.0;
	this->_y_start = 0.0;
	this->_y_end = 1.0;
}
Range::Range(double x_start,double x_end,double y_start,double y_end)
{
	this->_x_start = x_start;
	this->_x_end = x_end;
	this->_y_start = y_start;
	this->_y_end = y_end;
}
Range::Range(const Range& range)
{
	this->_x_start = range._x_start;
	this->_x_end = range._x_end;	
	this->_y_start = range._y_start;
	this->_y_end = range._y_end;
}
double Range::X_Start() const
{
	return this->_x_start;
}
double Range::X_End() const
{
	return this->_x_end;
}
double Range::Y_Start() const
{
	return this->_y_start;
}
double Range::Y_End() const
{
	return this->_y_end;
}

/************************************************************************
* CodeProcessor
*************************************************************************/
CodeProcessor::CodeProcessor(string code)
{
	this->_code = code;
}
CodeProcessor::~CodeProcessor()
{
	
}
list<ItemResult*>* CodeProcessor::Parse() const
{
	vector<string> vector_str = getFromCode();	
	list<ItemResult*>* p_list_ir = new list<ItemResult*>();
	this->doParse(0,Range(),p_list_ir,&vector_str);
	return p_list_ir;
}
bool CodeProcessor::CodeIsValid() const
{
	vector<string> vector_str = getFromCode();	
	return true;
}
vector<string> CodeProcessor::getFromCode() const
{
	vector<string> vector_str;
	int startpos = 0;
	int posofcomma = this->_code.find_first_of(",");
	while(posofcomma != -1)
	{
		vector_str.push_back(this->_code.substr(startpos,posofcomma - startpos));
		startpos = posofcomma + 1;
		posofcomma = this->_code.find_first_of(",",startpos);
	}
	vector_str.push_back(this->_code.substr(startpos));
	return vector_str;
}
void CodeProcessor::doParse(int index,const Range& range,list<ItemResult*>* p_list,vector<string>* p_vector_str) const
{
	StructParam* p_sp = StructParams::Create()->Get(p_vector_str->at(index));
	for(int i = 0; i < p_sp->UnitCount(); ++ i)
	{
		int x = index + i + 1;
		if(x >= p_vector_str->size()) break;

		Range range_i = p_sp->GetRange(i);
		double x_start = range.X_Start() + range_i.X_Start()*(range.X_End() - range.X_Start());
		double x_end = range.X_Start() + range_i.X_End()*(range.X_End() - range.X_Start());
		double y_start = range.Y_Start() + range_i.Y_Start()*(range.Y_End() - range.Y_Start());
		double y_end = range.Y_Start() + range_i.Y_End()*(range.Y_End() - range.Y_Start());
		Range* newRange = new Range(x_start,x_end,y_start,y_end);

		string item = p_vector_str->at(x);
		if(item.length() == 1)
		{
			doParse(x,*newRange,p_list,p_vector_str);
		}
		else
		{
			int x = newRange->X_Start()*32.0;
			int y = newRange->Y_Start()*32.0;
			int width = 32.0 * (newRange->X_End() - newRange->X_Start());
			int height = 32.0 * (newRange->Y_End() - newRange->Y_Start());
			p_list->push_back(new ItemResult(item,x,y,width,height));
		}
		delete newRange;
	}
	int counter = 0;
	for(vector<string>::iterator it = p_vector_str->begin();it != p_vector_str->end();it++)
	{
		if(counter == index)
		{
			it ++;
			vector<string>::iterator it_start = it;
			for(int i=0;i<p_sp->UnitCount();i++)
			{
				it++;
			}
			p_vector_str->erase(it_start,it);
			break;
		}
		counter ++;
	}
}
void CodeProcessor::doParse(int index,vector<string>* p_vector_str) const
{
	StructParam* p_sp = StructParams::Create()->Get(p_vector_str->at(index));
	for(int i = 0; i < p_sp->UnitCount(); ++ i)
	{
		int x = index + i + 1;
		if(x >= p_vector_str->size()) break;

		string item = p_vector_str->at(x);
		if(item.length() == 1)
		{
			doParse(x,p_vector_str);
		}
	}
	int counter = 0;
	for(vector<string>::iterator it = p_vector_str->begin();it != p_vector_str->end();it++)
	{
		if(counter == index)
		{
			it ++;
			vector<string>::iterator it_start = it;
			for(int i=0;i<p_sp->UnitCount();i++)
			{
				it++;
			}
			p_vector_str->erase(it_start,it);
			break;
		}
		counter ++;
	}
}